﻿using Microsoft.EntityFrameworkCore;

using NPOI.SS.Formula.Functions;

using PLCS.Application.Contracts.OrderApp;
using PLCS.Application.Contracts.OrderApp.Dtos;
using PLCS.Application.Contracts.TaskApp.Dtos;
using PLCS.Domain.Orders;
using PLCS.Domain.Shared.Orders;
using PLCS.Domain.Shared.Tasks;
using PLCS.Domain.Tasks;
using PLCS.Shared.Common.Constant;
using PLCS.Shared.Common.Extensions;

using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;

namespace PLCS.Application.OrderApp;

public class OrderAppService : CrudAppService<Order, OrderDto, Guid, PagedResultRequestDto, OrderEditDto>, IOrderAppService
{
    private readonly IOrderRepository _repository;
    private readonly IRepository<OrderRunningCondition> _orderRunningConditionRepository;

    public OrderAppService(IOrderRepository repository, IRepository<OrderRunningCondition> orderRunningConditionRepository) : base(repository)
    {
        _repository = repository;
        _orderRunningConditionRepository = orderRunningConditionRepository;
    }

    public override async Task DeleteAsync(Guid id)
    {
        var order = await _repository.GetAsync(id);
        var orderRunningConditions = await _orderRunningConditionRepository.GetListAsync(x => x.OrderNo == order.OrderNo);
        await _orderRunningConditionRepository.DeleteManyAsync(orderRunningConditions);
        await base.DeleteAsync(id);
    }

    /// <summary>
    /// 根据工单号查询
    /// </summary>
    /// <param name="orderNo"></param>
    /// <returns></returns>
    public async Task<OrderDto> GetByOrderNoAsync(string orderNo)
    {
        var order = await _repository.FindOrderByNoAsync(orderNo);
        Check.NotNull(order, orderNo, $"没有找到工单‘{orderNo}’");
        return ObjectMapper.Map<Order, OrderDto>(order);
    }

    /// <summary>
    /// 根据工单类型查询所有工单
    /// </summary>
    /// <param name="orderType"></param>
    /// <returns></returns>
    public async Task<IEnumerable<OrderDto>> GetListByType(OrderType orderType)
    {
        var orders = (await _repository.GetOrderListAsync(x => x.OrderType == orderType)).OrderByDescending(x => x.CreationTime);
        return ObjectMapper.Map<IEnumerable<Order>, IEnumerable<OrderDto>>(orders);
    }

    public async Task UpdateAsync(OrderEditDto orderDto)
    {
        await CheckUpdatePolicyAsync();

        var entity = await GetEntityByIdAsync(orderDto.Id);
        await MapToEntityAsync(orderDto, entity);
        await Repository.UpdateAsync(entity, autoSave: true);
    }

    public async Task<PagedResultDto<OrderDto>> GetListBySearchAsync(PagedResultRequestDto input, string? orderNo)
    {
        await CheckGetListPolicyAsync();

        var query = await ReadOnlyRepository.GetQueryableAsync();

        query = query.WhereIf(!string.IsNullOrEmpty(orderNo), x => x.OrderNo == orderNo)
            .OrderByDescending(x => x.CreationTime);
        var totalCount = await AsyncExecuter.CountAsync(query);

        query = ApplySorting(query, input);
        query = ApplyPaging(query, input);

        var entities = await AsyncExecuter.ToListAsync(query);
        foreach (var item in entities)
        {
            var orderRunningConditions = await _orderRunningConditionRepository.GetListAsync(x => x.OrderNo == item.OrderNo);
            item.OrderRunningConditions = orderRunningConditions.OrderBy(x => x.WhichStep).ToList();
        }
        var entityDtos = await MapToGetListOutputDtosAsync(entities);

        return new PagedResultDto<OrderDto>(
            totalCount,
            entityDtos
        );
    }
}